package org.xshop.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.transaction.annotation.Transactional;
import org.xshop.BizConstants.TradeStyle;
import org.xshop.mapper.TOrderMapper;
import org.xshop.model.TExpressmanAccount;
import org.xshop.model.TGoods;
import org.xshop.model.TOrder;
import org.xshop.model.TOrderFee;
import org.xshop.model.TOrderSku;
import org.xshop.model.TOrderStateLog;
import org.xshop.service.ITExpressmanAccountService;
import org.xshop.service.ITOrderExpressService;
import org.xshop.service.ITOrderStateService;

import com.alibaba.fastjson.JSON;
import com.weibo.api.motan.config.springsupport.annotation.MotanService;

import top.ibase4j.core.Constants;
import top.ibase4j.core.base.BaseServiceImpl;
import top.ibase4j.core.exception.BusinessException;
import top.ibase4j.core.support.generator.Sequence;
import top.ibase4j.core.support.pay.WxPayment;
import top.ibase4j.core.util.AlipayUtil;
import top.ibase4j.core.util.CacheUtil;
import top.ibase4j.core.util.DateUtil;
import top.ibase4j.core.util.DateUtil.DATE_PATTERN;
import top.ibase4j.core.util.InstanceUtil;
import top.ibase4j.core.util.PropertiesUtil;
import top.ibase4j.core.util.WeChatUtil;

@MotanService(interfaceClass = ITOrderStateService.class)
@CacheConfig(cacheNames = "order")
public class OrderStateService extends BaseServiceImpl<TOrder, TOrderMapper> implements ITOrderStateService {
    @Autowired
    private OrderSkuService orderSkuService;
    @Autowired
    private OrderStateLogService stateLogService;
    @Autowired
    private MemberNotifyService notifyService;
    @Autowired
    private SysService sysService;
    @Autowired
    private OrderFeeService orderFeeService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private ITExpressmanAccountService expressmanAccountService;
    @Autowired
    private ITOrderExpressService orderExpressService;

    /** TODO 微信回调 */
    @Override
    @Transactional
    public void updateWxPayReturn(Map<String, Object> param) {
        Map<String, String> params = InstanceUtil.newHashMap();
        for (String key : param.keySet()) {
            params.put(key, param.get(key).toString());
        }
        String signStr = params.get("sign");
        String sign = WxPayment.createSign(params, PropertiesUtil.getString("wx.partnerKey"));
        if (!sign.equals(signStr)) {
            throw new RuntimeException("参数错误.");
        }
        String return_code = params.get("return_code");
        if (WxPayment.codeIsOK(return_code)) {
            String orderNo = params.get("out_trade_no");
            TOrder order = new TOrder();
            order.setOrderNo(orderNo);
            order = selectOne(order);
            if (order == null) {
                throw new RuntimeException("商户订单号错误.");
            }
            if ("1".equals(order.getState())) {
                order.setPayOrderId(params.get("transaction_id"));
                order.setPayTime(DateUtil.stringToDate(params.get("time_end")));
                order.setPayOpenid(params.get("openid"));
                order.setPayResult("SUCCESS".equals(params.get("result_code")) ? "1" : "2");
                order = updatePayResult(order, false);
            }
        }
    }

    /** TODO 支付宝回调 */
    @Override
    @Transactional
    public void updateAliPayReturn(Map<String, Object> param) {
        String outTradeNo = (String)param.get("out_trade_no");
        String tradeNo = (String)param.get("trade_no");
        String subjects = (String)param.get("subject");
        String total_amount = (String)param.get("total_amount");
        String ips = (String)param.get("ip");
        String tradeStatus = (String)param.get("trade_status");
        String gmtCreate = (String)param.get("gmt_create");
        String sign = AlipayUtil.getSign(outTradeNo, subjects, null, new BigDecimal(total_amount), ips, "1D",
                "http://www.heiche.me/app/order/aliPayReturn.api");
        if (param.get("sign").toString().equals(sign)) {
            throw new BusinessException("参数错误.");
        }
        TOrder order = new TOrder();
        order.setOrderNo(outTradeNo);
        order = selectOne(order);
        if (order == null) {
            throw new RuntimeException("商户订单号错误.");
        }
        if ("1".equals(order.getState())) {
            order.setPayOrderId(tradeNo);
            order.setPayTime(DateUtil.stringToDate(gmtCreate));
            order.setPayResult("TRADE_SUCCESS".equals(tradeStatus) ? "1" : "2");
            order = updatePayResult(order, false);
        }
    }

    /** TODO 查询订单状态 */
    @Override
    @Transactional
    public Map<String, Object> updateState(Long id, Long memberId) {
        TOrder order = new TOrder();
        order.setId(id);
        order = selectOne(order);
        if (order == null) {
            throw new RuntimeException("订单号错误.");
        }
        if (order.getMemberId().longValue() != memberId.longValue()) {
            throw new RuntimeException("您不能查看别人的订单.");
        }
        order = updateOrderState(order);
        Map<String, Object> result = InstanceUtil.newHashMap();
        result.put("id", order.getId().toString());
        result.put("orderId", order.getOrderNo());
        result.put("state", order.getState().toString());
        result.put("stateDesc", order.getRemark());
        result.put("qrCode", order.getQrCode());
        if (order.getFee() != null) {
            result.put("amount", order.getFee().getPayAmount());
        }
        return result;
    }

    @Override
    @Transactional
    public TOrder updateOrderState(TOrder order) {
        if ("1".equals(order.getState())) { // 待支付
            if (TradeStyle.WECHAT.toString().equals(order.getPayType())) { // 微信
                Map<String, Object> result = WeChatUtil.queryOrder(order.getOrderNo());
                if ("1".equals(result.get("trade_state"))) {
                    order.setPayTime((Date)result.get("time_end"));
                    order.setPayOrderId((String)result.get("trade_no"));
                    order.setPayResult((String)result.get("trade_state"));
                    order = updatePayResult(order, true);
                } else {
                    order.setRemark((String)result.get("trade_state_desc"));
                }
            } else if (TradeStyle.WXAPPLET.toString().equals(order.getPayType())) { // 微信小程序
                Map<String, Object> result = WeChatUtil.queryOrder(PropertiesUtil.getString("wx.applet.mch_id"),
                    PropertiesUtil.getString("wx.applet.appId"), PropertiesUtil.getString("wx.applet.partnerKey"),
                    order.getOrderNo());
                if ("1".equals(result.get("trade_state"))) {
                    order.setPayTime((Date)result.get("time_end"));
                    order.setPayOrderId((String)result.get("trade_no"));
                    order.setPayResult((String)result.get("trade_state"));
                    order = updatePayResult(order, true);
                } else {
                    order.setRemark((String)result.get("trade_state_desc"));
                }
            } else if (TradeStyle.ALIPAY.toString().equals(order.getPayType())) { // 支付宝
                Map<?, ?> result = AlipayUtil.searchTreade(order.getOrderNo(), null);
                order.setPayResult((String)result.get("trade_state"));
                if ("1".equals(result.get("trade_state"))) {
                    order.setPayTime((Date)result.get("time_end"));
                    order.setPayOrderId((String)result.get("trade_no"));
                    order = updatePayResult(order, true);
                } else {
                    order.setRemark((String)result.get("trade_state_desc"));
                }
            }
        }
        return order;
    }

    // 支付成功后发送通知
    @Override
    @Transactional
    @SuppressWarnings("serial")
    public TOrder updatePayResult(TOrder order, boolean isSearch) {
        String key = Constants.CACHE_NAMESPACE + "ORDER-STATE" + order.getOrderNo();
        String requestId = Sequence.next().toString();
        if (CacheUtil.getLock(key, requestId, 60 * 60 * 24)) {
            try {
                TOrder record = super.queryById(order.getId());
                if ("1".equals(record.getState()) && "1".equals(order.getPayResult())) {
                    order.setState("3");
                    if ("0".equals(order.getSkuType())) {
                        TExpressmanAccount account = expressmanAccountService.queryById(order.getMemberId());
                        account.setOpenid(order.getPayOpenid());
                        expressmanAccountService.update(account);
                        order = super.update(order);
                    } else if ("1".equals(order.getSkuType())) {
                        TOrderSku entity = new TOrderSku();
                        entity.setOrderId(order.getId());
                        List<TOrderSku> skus = orderSkuService.queryList(entity);
                        StringBuilder sb = new StringBuilder();
                        for (TOrderSku orderSku : skus) {
                            TGoods goods = goodsService.queryById(orderSku.getSkuId());
                            if (goods.getStock().subtract(orderSku.getQuantity()).doubleValue() >= 0) {
                                goods.setStock(goods.getStock().subtract(orderSku.getQuantity()));
                                goodsService.updateData(goods);
                            } else {
                                sb.append(sb.length() > 0 ? "," : "").append(goods.getGoodsName());
                            }
                        }
                        if (sb.length() > 0) {
                            order.setRemark("所选商品[" + sb.toString() + "]库存不足,请等待采购");
                        }
                        order = super.update(order);
                        stateLogService.updateLog(InstanceUtil.to(order, TOrderStateLog.class));
                        orderExpressService.notification(order.getId());
                        String msg = sysService.getSysParam("ODR-PAY-MSG");
                        if (StringUtils.isNotBlank(msg)) {
                            msg = msg.replace("ODR", order.getOrderNo());
                            msg = msg.replace("DATE",
                                DateUtil.format(order.getPayTime(), DATE_PATTERN.YYYY_MM_DD_HH_MM_SS));
                            StringBuilder info = new StringBuilder();
                            for (TOrderSku sku : skus) {
                                TGoods goods = JSON.parseObject(sku.getSkuInfo(), TGoods.class);
                                if (info.length() > 0) {
                                    info = info.append(",");
                                }
                                Long orderId = order.getId();
                                order.setFee(orderFeeService.selectOne(new TOrderFee() {
                                    {
                                        setOrderId(orderId);
                                    }
                                }));
                                info = info.append(goods.getGoodsName()).append("，花费")
                                        .append(order.getFee().getPayAmount()).append("元");
                            }

                            msg = msg.replace("INFO", info);
                            notifyService.sendNotification(order.getMemberId(), "1", "支付通知", msg);
                        }
                    }
                    return order;
                } else if (!isSearch) {
                    return super.update(order);
                } else {
                    return record;
                }
            } finally {
                CacheUtil.unLock(key, requestId);
            }
        } else if (isSearch) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            order = updatePayResult(order, isSearch);
        }
        return order;
    }
}
